﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.Net;

namespace BomberManServer.Threading
{
    public class ThreadedSocket
    {
        private Thread thread { get; set; }
        public TcpListener socket { get; set; }

        public delegate void StartThreadHandler();
        public StartThreadHandler job;

        private EventWaitHandle wait_handle;

        public ThreadedSocket(int port)
        {
            // create the thread
            thread = new Thread(new ParameterizedThreadStart(thread_start));
            // doesnt keep alive the program if main thread is stopped
            thread.IsBackground = true;
            // create the socket
            socket = new TcpListener(IPAddress.Any, port);
            socket.Server.Blocking = false;
            // create the synchronizing handle
            wait_handle = new EventWaitHandle(false, EventResetMode.ManualReset);
            // starts the thread who will wait for signal
            thread.Start(this);
        }
        
        // real entry point of the new thread
        // reentrance to this object
        private void thread_start(object thread) {
            ((ThreadedSocket)thread).thread_start_object();
        }
        
        // entry point of the new thread
        private void thread_start_object()
        {
            // main loop of the thread
            while (true)
            {
                // block the thread indefinitely
                // so the thread needs to be called by an other thread
                wait_handle.WaitOne(Timeout.Infinite);
                // do the job you affected
                job();
            }
        }

        // called by main thread to wake the worker thread
        public void start(StartThreadHandler handler)
        {
            // start listening
            socket.Start(4);
            // give the delegate method you want the thread to execute
            this.job = handler;
            // wake the thread
            wait_handle.Set();
        }
    }
}
